home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 18 / CU Amiga Magazine's Super CD-ROM 18 (1997)(EMAP Images)(GB)[!][issue 1998-01].iso / CUCD / Online / SANA2Meter / Source / sana2meter.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-04  |  47.4 KB  |  1,529 lines

  1. /*
  2. ** $VER: sana2meter.c 1.98 (04 Jun 1996)
  3. **
  4. ** (C) Copyright 1996 Marius Gröger
  5. **     All Rights Reserved
  6. **
  7. ** $HISTORY:
  8. **
  9. ** 04 Jun 1996 : 001.009 :  memory for SpecialStatRecords was allocated
  10. **                          badly causing memory trashing
  11. ** 02 Jun 1996 : 001.008 :  support for statically linked gtlayout
  12. ** 05 May 1996 : 001.007 :  Screen jumping, Stay-front
  13. ** 04 May 1996 : 001.006 :  CPS display
  14. ** 25 Apr 1996 : 001.005 :  some parts moved to support.c, sana2meter.h
  15. ** 20 Apr 1996 : 001.004 :  support for multiple devices
  16. ** 15 Apr 1996 : 001.003 :  support for broken gadtools V39
  17. ** 14 Apr 1996 : 001.002 :  failing DoIO()'s will turn off further displaying
  18. **                          of the corresponding values
  19. ** 10 Apr 1996 : 001.001 :  packet type tracking
  20. ** 26 Mar 1996 : 001.000 :  created
  21. */
  22.  
  23. #define DEBUG 0
  24. #define USE_EXTREADARGS 1
  25. #define CATALOG_VERSION 5
  26.  
  27. /*F*/ /* includes */
  28.  
  29. #include <clib/alib_protos.h>
  30. #include <clib/dos_protos.h>
  31. #include <pragmas/dos_pragmas.h>
  32. #include <clib/utility_protos.h>
  33. #include <pragmas/utility_pragmas.h>
  34. #include <clib/exec_protos.h>
  35. #include <pragmas/exec_sysbase_pragmas.h>
  36. #include <clib/intuition_protos.h>
  37. #include <pragmas/intuition_pragmas.h>
  38. #include <clib/gadtools_protos.h>
  39. #include <pragmas/gadtools_pragmas.h>
  40. #include <clib/icon_protos.h>
  41. #include <pragmas/icon_pragmas.h>
  42. #include <clib/locale_protos.h>
  43. #include <pragmas/locale_pragmas.h>
  44. #include <gtlayout/gtlayout.h>
  45. #include <exec/libraries.h>
  46. #include <exec/devices.h>
  47. #include <exec/memory.h>
  48. #include <exec/io.h>
  49. #include <workbench/startup.h>
  50. #include <utility/tagitem.h>
  51. #include <netinclude:devices/sana2.h>
  52. #define AsmPools
  53. #include <pools/pool_lib.h>
  54.  
  55. #if (USE_EXTREADARGS != 0)
  56. #include <extrdargs.h>
  57. #endif
  58.  
  59. #include "compiler.h"
  60. #include "debug.h"
  61. #define CATCOMP_NUMBERS
  62. #include "locale.h"
  63. #include "sana2meter.h"
  64. #include "constdata.h"
  65.  
  66. #include <strings.h>
  67. #include <stddef.h>
  68. /*E*/
  69.  
  70. /*F*/ /* private symbols */
  71. PRIVATE BOOL parseargs(GD gd);
  72. PRIVATE VOID cleanup(GD gd);
  73. PRIVATE BOOL opendevs(GD gd);
  74. PRIVATE GD createenv(ULONG argc, UBYTE **argv);
  75. PRIVATE VOID getspeciallabels(GD gd);
  76. PRIVATE struct GlobalDevData *makedevice(GD gd, STRPTR devicename);
  77. PRIVATE VOID dummys2copy(VOID);
  78. /*E*/
  79. /*F*/ /* exported symbols */
  80. PUBLIC VOID SAVEDS STDARGS main(ULONG argc, UBYTE **argv);
  81. PUBLIC VOID saveconfig(GD gd);
  82. PUBLIC VOID updateupdate(GD gd, struct GlobalDevData *gdd);
  83. PUBLIC UWORD updateglobalstats(GD gd, struct GlobalDevData *gdd);
  84. PUBLIC UWORD updatespecialstats(GD gd, struct GlobalDevData *gdd);
  85. PUBLIC UWORD updatetracktype(GD gd, struct GlobalDevData *gdd);
  86. PUBLIC VOID updateactives(GD gd);
  87. /*E*/
  88. /*F*/ /* imported symbols */
  89. IMPORT struct Library *openlib(GD gd, STRPTR name, LONG version);
  90. IMPORT ASM STRPTR GetString(REG(a0) struct LocaleInfo *li, REG(d0) LONG stringNum);
  91. IMPORT STDARGS VOID exit(LONG);
  92. IMPORT STDARGS VOID sprintf(char *, char *, ...);
  93. IMPORT VOID message(GD gd, LONG, LONG, LONG, ...);
  94. IMPORT VOID *allocpvec(GD gd, ULONG len);
  95. IMPORT VOID freepvec(GD gd, VOID *mem);
  96. IMPORT VOID *allocppvec(GD gd, ULONG len);
  97. IMPORT VOID freeppvec(GD gd, VOID *mem);
  98. IMPORT BOOL preparemenu(GD gd);
  99. IMPORT BOOL dowindow(GD gd, DoWindowCtrl *ctrl);
  100. IMPORT VOID checkmenu(GD gd);
  101. IMPORT VOID updategui(GD gd, BOOL complete);
  102. IMPORT VOID closegui(GD gd);
  103. IMPORT BOOL opengui(GD gd);
  104. IMPORT ULONG strntolong(GD gd, STRPTR s, LONG *number, LONG n);
  105. IMPORT STRPTR AddToolType(GD gd, struct DiskObject *dobj, char *tool);
  106. IMPORT STRPTR *DupToolTypes(GD gd, struct DiskObject *dobj);
  107. IMPORT void UnDupToolTypes(GD gd, struct DiskObject *dobj, STRPTR *oldtt);
  108. /*E*/
  109.  
  110. /*F*/ /* constants for parsing */
  111. PRIVATE const UBYTE TEMPLATE[] = "DEV=DEVICE,"            \
  112.                                  "U=UNIT/K/N,"            \
  113.                                  "S=SHOW/K,"              \
  114.                                  "TT=TRACKTYPE/K,"        \
  115.                                  "FORCE/S,"               \
  116.                                  "OFF/S,"                 \
  117.                                  "FROM/K,"                \
  118.                                  "RF=REFRESH/K/N,"        \
  119.                                  "CPSA=CPSAGING/K/N,"     \
  120.                                  "L=LIST/S,"              \
  121.                                  "FONT=FONTNAME/K,"       \
  122.                                  "FONTSIZE/K/N,"          \
  123.                                  "TOP/K/N,"               \
  124.                                  "LEFT/K/N,"              \
  125.                                  "SCREEN=PUBSCREEN/K,"    \
  126.                                  "NA=NOACTIVATE/S,"       \
  127.                                  "W2B=WINDOWTOBACK/S,"    \
  128.                                  "SF=STAYFRONT/S,"        \
  129.                                  "WINDOW/K";
  130.  
  131. enum
  132. {
  133.    ARG_DEVICE,
  134.    ARG_UNIT,
  135.    ARG_SHOW,
  136.    ARG_TRACKTYPE,
  137.    ARG_FORCE,
  138.    ARG_OFF,
  139.    ARG_FROM,
  140.    ARG_REFRESH,
  141.    ARG_CPSAGING,
  142.    ARG_LIST,
  143.    ARG_FONT,
  144.    ARG_FONTSIZE,
  145.    ARG_TOP,
  146.    ARG_LEFT,
  147.    ARG_PUBSCREEN,
  148.    ARG_NOACTIVATE,
  149.    ARG_WINDOWTOBACK,
  150.    ARG_STAYFRONT,
  151.    ARG_WINDOW,
  152.    ARG_COUNT
  153. };
  154.  
  155.  
  156. #define DEF_UNIT 0
  157. #define DEF_CPSAGING 20
  158. #define DEF_REFRESH 2
  159. #define DEF_FONTSIZE 8
  160. #define DEF_LEFT 30
  161. #define DEF_TOP 20
  162.  
  163. PRIVATE UBYTE KEYDELIMITERS[]   = ",;| ";
  164. PRIVATE UBYTE TTMASKSEPARATOR[] = ":/";
  165. PRIVATE UBYTE TTMASKACTIVE[]    = "+xX#";
  166. PRIVATE UBYTE TTMASKINACTIVE[]  = "-oO.";
  167.  
  168. /*E*/
  169.  
  170. /*F*/ PRIVATE struct GlobalDevData *makedevice(GD gd, STRPTR devicename)
  171. {
  172.    const struct NewWatch * nw;
  173.    struct Watch *w;
  174.    struct Sana2SpecialStatRecord *sr;
  175.    struct GlobalDevData *gdd;
  176.    struct PublicDevData *pdd;
  177.    BOOL rc = FALSE;
  178.  
  179.    if (gdd = allocpvec(gd, sizeof(struct GlobalDevData) + strlen(devicename)))
  180.    {
  181.       strcpy((char*)gdd->gd_Device, devicename);
  182.       gdd->gd_Unit = DEF_UNIT;
  183.       gdd->gd_Active = 1;
  184.       NewList((struct List*)&gdd->gd_Watches);
  185.  
  186.       if (pdd = gdd->gd_Public = allocppvec(gd, sizeof(struct PublicDevData) +
  187.                    (NUM_SPECIALSTATS-1)*sizeof(struct Sana2SpecialStatRecord)))
  188.       {
  189.          sr = pdd->pd_S2SpecialStatRecs;
  190.  
  191.          rc = TRUE;
  192.  
  193.          if (gdd->gd_StdWatches = allocpvec(gd, (NUM_SPECIALSTATS+NUM_STDWATCHES)*sizeof(struct Watch)))
  194.          {
  195.             /* create all the watches from the NewWatch array */
  196.             for (w = gdd->gd_StdWatches, nw = stdwatches; nw->nw_Member != MEMBER_NONE; ++nw, ++w)
  197.             {
  198.                w->w_Member = nw->nw_Member;
  199.                w->w_Key = nw->nw_Key;
  200.                w->w_ShortKey = nw->nw_ShortKey;
  201.                if (!(nw->nw_Flags & WF_NOLABEL))
  202.                   w->w_Label = GetString(&gd->gd_LocaleInfo, nw->nw_LabelID);
  203.                w->w_Flags = nw->nw_Flags;
  204.  
  205.                if (nw->nw_Member == MEMBER_GLOBALSTATS)
  206.                   w->w_Value = (ULONG*)((UBYTE*)&pdd->pd_S2DeviceStats + nw->nw_StructOffset);
  207.                else if (nw->nw_Member == MEMBER_DEVICEQUERY)
  208.                   w->w_Value = (ULONG*)((UBYTE*)&pdd->pd_S2DeviceQuery + nw->nw_StructOffset);
  209.                else if (nw->nw_Member == MEMBER_SPECIALSTATS)
  210.                {
  211.                   w->w_Value = &sr->Count;
  212.                   ++sr;
  213.                }
  214.                else
  215.                   w->w_Value = NULL;
  216.  
  217.                AddTail((struct List*)&gdd->gd_Watches, (struct Node*)&w->w_Link);
  218.             }
  219.          } else rc = FALSE;
  220.       }
  221.  
  222.       if (!rc)
  223.       {
  224.          if (gdd->gd_StdWatches) freepvec(gd, gdd->gd_StdWatches);
  225.          if (gdd->gd_Public) freepvec(gd, gdd->gd_Public);
  226.          freepvec(gd, gdd);
  227.          gdd = NULL;
  228.       }
  229.    }
  230.  
  231.    return gdd;
  232. }
  233. /*E*/
  234. /*F*/ PRIVATE BOOL preparetts(GD gd)
  235. {
  236.    struct NewWatch *nw;
  237.    struct TrackType *tt;
  238.    struct Watch *w;
  239.    BOOL rc = TRUE, first;
  240.    ULONG numtt, i;
  241.    struct GlobalDevData *gdd;
  242.    struct PublicDevData *pdd;
  243.  
  244.    SCANDEVS(gdd, &gd->gd_Devices)
  245.    {
  246.       pdd = gdd->gd_Public;
  247.       if (gdd->gd_TrackWatches = allocpvec(gd, NUM_TTWATCHES*gdd->gd_NumTT*sizeof(struct Watch)))
  248.       {
  249.          w = gdd->gd_TrackWatches;
  250.          for (tt=pdd->pd_TrackedTypes, numtt = gdd->gd_NumTT; numtt; ++tt,  --numtt)
  251.          {
  252.             for (i=0, first=TRUE, nw=(struct NewWatch *)ttwatches; nw->nw_Member != MEMBER_NONE;
  253.                                                                         ++i, ++nw, first=FALSE)
  254.             {
  255.                w->w_Member = nw->nw_Member;
  256.                w->w_TrackType = tt;
  257.                w->w_Key = first ? tt->tt_Key : NULL;
  258.                w->w_Label = GetString(&gd->gd_LocaleInfo, nw->nw_LabelID);
  259.                w->w_Flags = nw->nw_Flags | (first ? WF_FIRSTTT : 0);
  260.                if (tt->tt_Flags & TTF_INITIAL_SETUP)
  261.                {
  262.                   if (tt->tt_Flags & ttmaskflags[i])
  263.                      w->w_Flags |= WF_ACTIVE;
  264.                   else
  265.                      w->w_Flags &= ~WF_ACTIVE;
  266.                }
  267.                tt->tt_Flags |= TTF_DROPFIRSTCPS;
  268.                w->w_Value = (ULONG*)((UBYTE*)tt + nw->nw_StructOffset);
  269.                AddTail((struct List*)&gdd->gd_Watches, (struct Node*)&w->w_Link);
  270.  
  271.                ++w;
  272.             }
  273.          }
  274.       }
  275.    }
  276.    return rc;
  277. }
  278. /*E*/
  279. /*F*/ PRIVATE VOID getspeciallabels(GD gd)
  280. {
  281.    struct Watch *w;
  282.    BOOL specials;
  283.    struct GlobalDevData *gdd;
  284.    struct PublicDevData *pdd;
  285.  
  286.    SCANDEVS(gdd, &gd->gd_Devices)
  287.    {
  288.       pdd = gdd->gd_Public;
  289.       specials = FALSE;
  290.  
  291.       gdd->gd_ValidSpecialStats = 0;
  292.  
  293.       SCANWATCHES(w, &gdd->gd_Watches)
  294.       {
  295.          if (!specials)
  296.          {
  297.             if (w->w_Member == MEMBER_SPECIALSTATS)
  298.                specials = TRUE;
  299.          }
  300.          if (specials)
  301.          {
  302.             if ((gdd->gd_ValidSpecialStats >= NUM_SPECIALSTATS) ||
  303.                 (gdd->gd_ValidSpecialStats >= pdd->pd_S2SpecialStats.RecordCountSupplied))
  304.                break;
  305.             w->w_Label = pdd->pd_S2SpecialStatRecs[gdd->gd_ValidSpecialStats].String;
  306.             ++gdd->gd_ValidSpecialStats;
  307.          }
  308.       }
  309.    }
  310.  
  311.    return ;
  312. }
  313. /*E*/
  314.  
  315. /*F*/ PUBLIC VOID updateactives(GD gd)
  316. {
  317.    struct GlobalDevData *gdd;
  318.  
  319.    gd->gd_NeedTimer = 0;
  320.    gd->gd_NumActives = 0;
  321.    SCANDEVS(gdd, &gd->gd_Devices)
  322.    {
  323.       d(("device <%s>\n", gdd->gd_Device));
  324.  
  325.       if (!gdd->gd_GetGlobalStats && !gdd->gd_GetSpecialStats &&
  326.            !gdd->gd_GetTrackType && !gdd->gd_ShowDevQuery)
  327.          gdd->gd_Active = 0;
  328.       else
  329.       {
  330.          if (gdd->gd_Active)
  331.          {
  332.             if (gdd->gd_GetGlobalStats || gdd->gd_GetSpecialStats || gdd->gd_GetTrackType)
  333.                gd->gd_NeedTimer = 1;
  334.  
  335.             ++gd->gd_NumActives;
  336.          }
  337.       }
  338.       d(("GetGlobalStats %ld, GetSpecialStats %ld, GetTrackType %ld, Active %ld\n",
  339.          gdd->gd_GetGlobalStats, gdd->gd_GetSpecialStats, gdd->gd_GetTrackType, gdd->gd_Active));
  340.  
  341.    }
  342.    d(("NeedTimer %ld, NumActives %ld\n", gd->gd_NeedTimer, gd->gd_NumActives));
  343. }
  344. /*E*/
  345. /*F*/ PUBLIC VOID updateupdate(GD gd, struct GlobalDevData *gdd)
  346. {
  347.    struct Watch *w;
  348.    struct TrackType *tt;
  349.    ULONG i;
  350.    struct PublicDevData *pdd;
  351.  
  352.    pdd = gdd->gd_Public;
  353.  
  354.    gdd->gd_GetGlobalStats = 0;
  355.    gdd->gd_GetSpecialStats = 0;
  356.    gdd->gd_GetTrackType = 0;
  357.    gdd->gd_ShowDevQuery = 0;
  358.  
  359.    for(i=gdd->gd_NumTT, tt=pdd->pd_TrackedTypes; i; --i, ++tt)
  360.       tt->tt_Flags &= ~TTF_ACTIVE;
  361.  
  362.    SCANWATCHES(w, &gdd->gd_Watches)
  363.    {
  364.       if ((w->w_Flags & WF_ACTIVE) && (w->w_Member == MEMBER_DEVICEQUERY))
  365.          gdd->gd_ShowDevQuery = 1;
  366.  
  367.       if ((w->w_Flags & WF_ACTIVE) && (w->w_Member == MEMBER_GLOBALSTATS))
  368.          gdd->gd_GetGlobalStats = 1;
  369.  
  370.       if ((w->w_Flags & WF_ACTIVE) && (w->w_Member == MEMBER_SPECIALSTATS))
  371.          gdd->gd_GetSpecialStats = 1;
  372.  
  373.       if (w->w_Member == MEMBER_TRACKTYPE)
  374.       {
  375.          if (w->w_Flags & WF_ACTIVE)
  376.          {
  377.             w->w_TrackType->tt_Flags |= TTF_ACTIVE;
  378.             gdd->gd_GetTrackType = 1;
  379.          }
  380.       }
  381.    }
  382.    return ;
  383. }
  384. /*E*/
  385. /*F*/ PUBLIC UWORD updateglobalstats(GD gd, struct GlobalDevData *gdd)
  386. {
  387.    struct PublicDevData *pdd;
  388.    UWORD rc = 0;
  389.  
  390.    pdd = gdd->gd_Public;
  391.    pdd->pd_S2Req.ios2_StatData = (void*)&pdd->pd_S2DeviceStats;
  392.    pdd->pd_S2Req.ios2_Req.io_Command = S2_GETGLOBALSTATS;
  393.    if (DoIO((struct IORequest*)&pdd->pd_S2Req))
  394.    {
  395.       struct Watch *w;
  396.  
  397.       SCANWATCHES(w, &gdd->gd_Watches)
  398.       {
  399.          if (w->w_Member == MEMBER_GLOBALSTATS)
  400.             w->w_Flags = (w->w_Flags & ~WF_ACTIVE) | WF_OFF;
  401.       }
  402.       rc = 1;
  403.    }
  404.    return rc;
  405. }
  406. /*E*/
  407. /*F*/ PUBLIC UWORD updatespecialstats(GD gd, struct GlobalDevData *gdd)
  408. {
  409.    struct PublicDevData *pdd;
  410.    UWORD rc = 0;
  411.  
  412.    pdd = gdd->gd_Public;
  413.    pdd->pd_S2SpecialStats.RecordCountMax = NUM_SPECIALSTATS;
  414.    pdd->pd_S2Req.ios2_StatData = (void*)&pdd->pd_S2SpecialStats;
  415.    pdd->pd_S2Req.ios2_Req.io_Command = S2_GETSPECIALSTATS;
  416.    if (DoIO((struct IORequest*)&pdd->pd_S2Req))
  417.    {
  418.       struct Watch *w;
  419.  
  420.       SCANWATCHES(w, &gdd->gd_Watches)
  421.       {
  422.          if (w->w_Member == MEMBER_SPECIALSTATS)
  423.             w->w_Flags = (w->w_Flags & ~WF_ACTIVE) | WF_OFF;
  424.       }
  425.       rc = 1;
  426.    }
  427.    return rc;
  428. }
  429. /*E*/
  430. /*F*/ PUBLIC UWORD updatetracktype(GD gd, struct GlobalDevData *gdd)
  431. {
  432.    struct PublicDevData *pdd;
  433.    struct TrackType *tt;
  434.    ULONG i;
  435.    UWORD rc = 0;
  436.    ULONG old_ibytes, old_obytes;
  437.  
  438.    pdd = gdd->gd_Public;
  439.    for(i=gdd->gd_NumTT, tt=pdd->pd_TrackedTypes; i; --i, ++tt)
  440.    {
  441.       if (tt->tt_Flags & TTF_ACTIVE)
  442.       {
  443.          old_ibytes = tt->tt_Stats.BytesReceived;
  444.          old_obytes = tt->tt_Stats.BytesSent;
  445.          pdd->pd_S2Req.ios2_StatData = (void*)&tt->tt_Stats;
  446.          pdd->pd_S2Req.ios2_Req.io_Command = S2_GETTYPESTATS;
  447.          if (DoIO((struct IORequest*)&pdd->pd_S2Req))
  448.          {
  449.             struct Watch *w;
  450.  
  451.             SCANWATCHES(w, &gdd->gd_Watches)
  452.             {
  453.                if (w->w_TrackType == tt)
  454.                   w->w_Flags = (w->w_Flags & ~WF_ACTIVE) | WF_OFF;
  455.             }
  456.             rc = 1;
  457.          }
  458.          else
  459.          {
  460.             if (tt->tt_Flags & TTF_DROPFIRSTCPS)
  461.                tt->tt_Flags &= ~TTF_DROPFIRSTCPS;
  462.             else
  463.             {
  464.                tt->tt_OCPS = (gd->gd_CPSAging * tt->tt_OCPS +
  465.                               gd->gd_CPSAgingComp *
  466.                                     ((tt->tt_Stats.BytesSent - old_obytes) / gd->gd_Refresh)
  467.                               ) / 100;
  468.  
  469.                tt->tt_ICPS = (gd->gd_CPSAging * tt->tt_ICPS +
  470.                               gd->gd_CPSAgingComp *
  471.                                     ((tt->tt_Stats.BytesReceived - old_ibytes) / gd->gd_Refresh)
  472.                               ) / 100;
  473.             }
  474.          }
  475.       }
  476.    }
  477.    return rc;
  478. }
  479. /*E*/
  480.  
  481. /*F*/ PRIVATE LONG nextkey(STRPTR arg, STRPTR *next)
  482. {
  483.    STRPTR nx;
  484.    LONG len;
  485.  
  486.    if ((nx = strpbrk(arg, KEYDELIMITERS)) != NULL)
  487.    {
  488.       len = nx - arg;
  489.       ++nx;
  490.    }
  491.    else
  492.    {
  493.       len = strlen(arg);
  494.       nx = arg + len;
  495.    }
  496.  
  497.    *next = nx;
  498.    return len;
  499. }
  500. /*E*/
  501. /*F*/ PRIVATE BOOL nowparse(GD gd, LONG param[ARG_COUNT], BOOL *more, BOOL fromconfig)
  502. {
  503.    PD pd = gd->gd_Public;
  504.    struct GlobalDevData *gdd;
  505.    BOOL rc = TRUE;
  506.    LONG len;
  507.  
  508.    *more = FALSE;
  509.  
  510.    if (param[ARG_WINDOW])
  511.       strncpy((char*)pd->pd_Console, (char*)param[ARG_PUBSCREEN], sizeof(pd->pd_Console));
  512.  
  513.    if (param[ARG_LIST])
  514.    {
  515.       gd->gd_List = 1;
  516.    }
  517.    else
  518.    {
  519.       if (param[ARG_FROM])
  520.       {
  521.          if (gd->gd_ConfigName) freepvec(gd, gd->gd_ConfigName);
  522.          if (gd->gd_ConfigName = allocpvec(gd, strlen((char*)param[ARG_FROM])))
  523.          {
  524.             strcpy(gd->gd_ConfigName, (char*)param[ARG_FROM]);
  525.             *more = TRUE;
  526.          }
  527.          else rc = FALSE;
  528.       }
  529.  
  530.       /* DEVICE/A */
  531.       if (param[ARG_DEVICE])
  532.       {
  533.          if (gdd = makedevice(gd, (STRPTR)param[ARG_DEVICE]))
  534.          {
  535.             gdd->gd_FromConfig = fromconfig ? 1 : 0;
  536.  
  537.             /* UNIT/K/N */
  538.             if (param[ARG_UNIT])
  539.                gdd->gd_Unit = *(LONG*)param[ARG_UNIT];
  540.  
  541.             /* OFF/S */
  542.             gdd->gd_Active = (param[ARG_OFF] == 0);
  543.  
  544.             /* FORCE/S */
  545.             gdd->gd_Force = (param[ARG_FORCE] != 0);
  546.  
  547.             /* SHOW/K */
  548.             if (param[ARG_SHOW])
  549.             {
  550.                STRPTR arg, next;
  551.                struct Watch *w;
  552.  
  553.                SCANWATCHES(w, &gdd->gd_Watches)
  554.                {
  555.                   w->w_Flags &= ~WF_ACTIVE;
  556.                }
  557.                arg = (STRPTR)param[ARG_SHOW];
  558.                while(len = nextkey(arg, &next))
  559.                {
  560.                   SCANWATCHES(w, &gdd->gd_Watches)
  561.                   {
  562.                      if (!Strnicmp(w->w_Key, arg, len) || !Strnicmp(w->w_ShortKey, arg, len))
  563.                      {
  564.                         w->w_Flags |= WF_ACTIVE;
  565.                         break;
  566.                      }
  567.                   }
  568.                   arg = next;
  569.                }
  570.             }
  571.  
  572.             /* TRACKTYPE/K */
  573.             if (param[ARG_TRACKTYPE])
  574.             {
  575.                STRPTR arg, next;
  576.                WORD clen, i;
  577.                struct PublicDevData *pdd = gdd->gd_Public;
  578.  
  579.                arg = (STRPTR)param[ARG_TRACKTYPE];
  580.                while(len = nextkey(arg, &next))
  581.                {
  582.                   ++gdd->gd_NumTT;
  583.                   arg = next;
  584.                }
  585.  
  586.                if (pdd->pd_TrackedTypes = allocpvec(gd, gdd->gd_NumTT * sizeof(struct TrackType)))
  587.                {
  588.                   struct TrackType *tt = pdd->pd_TrackedTypes;
  589.                   STRPTR fmt;
  590.  
  591.                   arg = (STRPTR)param[ARG_TRACKTYPE];
  592.                   while(len = nextkey(arg, &next))
  593.                   {
  594.                      if (clen = strntolong(gd, arg, (LONG*)&tt->tt_Type, len))
  595.                      {
  596.                         tt->tt_Flags = 0;
  597.                         fmt = GetString(&gd->gd_LocaleInfo, TXT_TTLABEL);
  598.                         sprintf(tt->tt_Label, fmt, tt->tt_Type);
  599.                         sprintf(tt->tt_Key, "$%lx", tt->tt_Type);
  600.                         if (clen != len)
  601.                         {
  602.                            if (strchr(TTMASKSEPARATOR, arg[clen]) != NULL)
  603.                            {
  604.                               tt->tt_Flags |= TTF_INITIAL_SETUP;
  605.                               for(++clen, i=0; clen < len; ++clen, ++i)
  606.                               {
  607.                                  if (strchr(TTMASKACTIVE, arg[clen]) != NULL)
  608.                                     tt->tt_Flags |= ttmaskflags[i];
  609.                                  else if (strchr(TTMASKINACTIVE, arg[clen]) == NULL)
  610.                                  {
  611.                                     d(("bad ttmask char: %lc (%02lx)\n",arg[clen],arg[clen]));
  612.                                     rc = FALSE;
  613.                                     break;
  614.                                  }
  615.                               }
  616.                            }
  617.                         }
  618.                         ++tt;
  619.                      }
  620.                      else --gdd->gd_NumTT;
  621.  
  622.                      arg = next;
  623.                   }
  624.                }
  625.             }
  626.             AddTail((struct List*)&gd->gd_Devices, (struct Node*)gdd);
  627.             ++gd->gd_NumDevices;
  628.          }
  629.       }
  630.  
  631.       if (rc)
  632.       {
  633.          if (!gd->gd_HadRefresh && param[ARG_REFRESH])
  634.          {
  635.             gd->gd_Refresh = *(LONG*)(param[ARG_REFRESH]);
  636.             gd->gd_HadRefresh = 1;
  637.          }
  638.  
  639.          if (!gd->gd_HadCPSAging && param[ARG_CPSAGING])
  640.          {
  641.             if (*(LONG*)(param[ARG_CPSAGING]) > 50 || *(LONG*)(param[ARG_CPSAGING]) < 0)
  642.             {
  643.                message(gd, REQ_ERROR_TITLE, REQ_ERROR_BADAGING,
  644.                                                     REQ_ERROR_QUITBUTTON);
  645.                rc = FALSE;
  646.             }
  647.             else
  648.             {
  649.                gd->gd_CPSAging = *(LONG*)(param[ARG_CPSAGING]);
  650.                gd->gd_CPSAgingComp = 100 - gd->gd_CPSAging;
  651.                gd->gd_HadCPSAging = 1;
  652.             }
  653.          }
  654.  
  655.          if (!gd->gd_HadFont && param[ARG_FONT])
  656.          {
  657.             gd->gd_CustomFont = 1;
  658.             strncpy(pd->pd_Fontname, (char*)param[ARG_FONT], sizeof(pd->pd_Fontname));
  659.             pd->pd_Font.tta_Name = (STRPTR)pd->pd_Fontname;
  660.             pd->pd_Font.tta_YSize = param[ARG_FONTSIZE] ? *(LONG*)(param[ARG_FONTSIZE]) : DEF_FONTSIZE;
  661.             pd->pd_Font.tta_Style = FS_NORMAL;
  662.             pd->pd_Font.tta_Flags = FPF_DISKFONT;
  663.             pd->pd_Font.tta_Tags = NULL;
  664.             gd->gd_HadFont = 1;
  665.          }
  666.  
  667.          if (!gd->gd_HadLeft && param[ARG_LEFT])
  668.          {
  669.             gd->gd_Left = *(LONG*)(param[ARG_LEFT]);
  670.             gd->gd_HadLeft = 1;
  671.          }
  672.  
  673.          if (!gd->gd_HadTop && param[ARG_TOP])
  674.          {
  675.             gd->gd_Top = *(LONG*)(param[ARG_TOP]);
  676.             gd->gd_HadTop = 1;
  677.          }
  678.  
  679.          if (!gd->gd_HadInactive && param[ARG_NOACTIVATE])
  680.          {
  681.             gd->gd_Inactive = 1;
  682.             gd->gd_HadInactive = 1;
  683.          }
  684.  
  685.          if (!gd->gd_HadWindowToBack && param[ARG_WINDOWTOBACK])
  686.          {
  687.             gd->gd_ToBack = 1;
  688.             gd->gd_HadWindowToBack = 1;
  689.          }
  690.  
  691.          if (!gd->gd_HadStayFront && param[ARG_STAYFRONT])
  692.          {
  693.             gd->gd_StayFront = 1;
  694.             gd->gd_HadStayFront = 1;
  695.          }
  696.  
  697.          if (!gd->gd_HadPubscreen && param[ARG_PUBSCREEN])
  698.          {
  699.             strncpy((char*)pd->pd_Pubscreen, (char*)param[ARG_PUBSCREEN],
  700.                                                    sizeof(pd->pd_Pubscreen));
  701.             gd->gd_HadPubscreen = 1;
  702.          }
  703.       }
  704.    }
  705.  
  706.    return rc;
  707. }
  708. /*E*/
  709. /*F*/ PRIVATE BOOL parseargs(GD gd)
  710. {
  711.    PD pd = gd->gd_Public;
  712.    BOOL rc = FALSE;
  713.    LONG param[ARG_COUNT];
  714.    BOOL more;
  715. #if (USE_EXTREADARGS != 0)
  716.    struct ExtRDArgs eargs = {NULL};
  717.  
  718.    eargs.erda_Window        = (STRPTR)DEF_CONSOLE;
  719.    eargs.erda_Template      = (STRPTR)TEMPLATE;
  720.    eargs.erda_Parameter     = param;
  721.    eargs.erda_FileParameter = -1;
  722.    eargs.erda_SysBase       = SysBase;
  723.    eargs.erda_DOSBase       = DOSBase;
  724.    eargs.erda_IconBase      = IconBase;
  725. #else
  726.    struct RDArgs *rda;
  727. #endif
  728.  
  729.    memset(param, '\0', sizeof(param));
  730.  
  731. #if (USE_EXTREADARGS != 0)
  732.    if (ExtReadArgs(gd->gd_argc, (STRPTR*)gd->gd_argv, &eargs) == 0)
  733. #else
  734.    if (rda = ReadArgs((STRPTR)TEMPLATE, param, NULL))
  735. #endif
  736.    {
  737.       /* some default values */
  738.       gd->gd_CPSAging = DEF_CPSAGING;
  739.       gd->gd_CPSAgingComp = 100 - DEF_CPSAGING;
  740.       gd->gd_Refresh = DEF_REFRESH;
  741.       gd->gd_CustomFont = 0;
  742.       gd->gd_Top = DEF_TOP;
  743.       gd->gd_Left = DEF_LEFT;
  744.       strncpy((char*)pd->pd_Console, DEF_CONSOLE, sizeof(pd->pd_Console));
  745.  
  746.       rc = nowparse(gd, param, &more, FALSE);
  747.       if (rc && !gd->gd_List)
  748.       {
  749.          BPTR file;
  750.          struct RDArgs *mrda, *xrda;
  751.          STRPTR line;
  752.  
  753.          while(rc && more)
  754.          {
  755.             if (file = Open(gd->gd_ConfigName, MODE_OLDFILE))
  756.             {
  757.                if (line = allocppvec(gd, 1024))
  758.                {
  759.                   if (mrda = AllocDosObject(DOS_RDARGS, NULL))
  760.                   {
  761.                      while(FGets(file, line, 1024))
  762.                      {
  763.                         d(("line : <%s>\n",line));
  764.                         mrda->RDA_Source.CS_Buffer = line;
  765.                         mrda->RDA_Source.CS_Length = strlen(line);
  766.                         mrda->RDA_Source.CS_CurChr = 0;
  767.                         mrda->RDA_Flags |= RDAF_NOPROMPT;
  768.                         memset(param, '\0', sizeof(param));
  769.                         if (xrda = ReadArgs((STRPTR)TEMPLATE, param, mrda))
  770.                         {
  771.                            nowparse(gd, param, &more, TRUE);
  772.                            FreeArgs(xrda);
  773.                         }
  774.                         else break;
  775.                      }
  776.                      if (gd->gd_NumDevices == 0)
  777.                      {
  778.                         message(gd, REQ_ERROR_TITLE, REQ_ERROR_READARGS,
  779.                                                             REQ_ERROR_QUITBUTTON, IoErr());
  780.                         rc = FALSE;
  781.                      }
  782.                      FreeDosObject(DOS_RDARGS, mrda);
  783.                   }
  784.                   else
  785.                   {
  786.                      message(gd, REQ_ERROR_TITLE, REQ_ERROR_READARGS,
  787.                                                          REQ_ERROR_QUITBUTTON, IoErr());
  788.                      rc = FALSE;
  789.                   }
  790.                   freeppvec(gd, line);
  791.                }
  792.                Close(file);
  793.             }
  794.             else
  795.             {
  796.                message(gd, REQ_ERROR_TITLE, REQ_ERROR_NOCONFIG, REQ_ERROR_QUITBUTTON, gd->gd_ConfigName);
  797.                rc = FALSE;
  798.             }
  799.          }
  800.       }
  801.  
  802.       if (!gd->gd_List && IsListEmpty((struct List*)&gd->gd_Devices))
  803.       {
  804.          message(gd, REQ_ERROR_TITLE, REQ_ERROR_NODEVS, REQ_ERROR_QUITBUTTON);
  805.          rc = FALSE;
  806.       }
  807.  
  808. #if (USE_EXTREADARGS != 0)
  809.       ExtFreeArgs(&eargs);
  810. #else
  811.       FreeArgs(rda);
  812. #endif
  813.    }
  814.    else
  815.    {
  816.       if (gd->gd_CLI)
  817.          PrintFault(IoErr(),gd->gd_ProgramName);
  818.       else
  819.          message(gd, REQ_ERROR_TITLE, REQ_ERROR_READARGS,
  820.                                           REQ_ERROR_QUITBUTTON, IoErr());
  821.    }
  822.    return(rc);
  823. }
  824. /*E*/
  825. /*F*/ PRIVATE VOID openconsole(GD gd)
  826. {
  827.    struct PublicData *pd = gd->gd_Public;
  828.  
  829.    if (!gd->gd_CLI)
  830.    {
  831.       if (gd->gd_Output = Open(pd->pd_Console, MODE_OLDFILE))
  832.       {
  833.          gd->gd_OldConsoleTask = SetConsoleTask(((struct FileHandle*)BADDR(gd->gd_Output))->fh_Type);
  834.          gd->gd_OldOutput = SelectOutput(gd->gd_Output);
  835.          gd->gd_OutputSelected = 1;
  836.          gd->gd_CTSelected = 1;
  837.          if (gd->gd_Input = Open("*", MODE_OLDFILE))
  838.          {
  839.             gd->gd_OldInput = SelectInput(gd->gd_Input);
  840.             gd->gd_InputSelected = 1;
  841.          }
  842.          else d(("no input\n"));
  843.       }
  844.       else d(("no output\n"));
  845.    }
  846. }
  847. /*E*/
  848. /*F*/ PRIVATE VOID cleanup(GD gd)
  849. {
  850.    PD pd = gd->gd_Public;
  851.    struct GlobalDevData *gdd;
  852.  
  853.    closegui(gd);
  854.    if (pd && pd->pd_TReq.tr_node.io_Device) CloseDevice((struct IORequest*)&pd->pd_TReq);
  855.    SCANDEVS(gdd, &gd->gd_Devices)
  856.    {
  857.       struct PublicDevData *pdd = gdd->gd_Public;
  858.       struct TrackType *tt;
  859.       ULONG i;
  860.  
  861.       if (pdd->pd_S2Req.ios2_Req.io_Device)
  862.       {
  863.          for(i=gdd->gd_NumTT, tt=pdd->pd_TrackedTypes; i; --i, ++tt)
  864.          {
  865.             if (tt->tt_Flags & TTF_TRACKED)
  866.             {
  867.                pdd->pd_S2Req.ios2_PacketType = tt->tt_Type;
  868.                pdd->pd_S2Req.ios2_Req.io_Command = S2_UNTRACKTYPE;
  869.                DoIO((struct IORequest*)&pdd->pd_S2Req);
  870.             }
  871.          }
  872.          CloseDevice((struct IORequest*)&pdd->pd_S2Req);
  873.       }
  874.    }
  875.    if (gd->gd_S2Port) DeleteMsgPort(gd->gd_S2Port);
  876.    if (gd->gd_TPort) DeleteMsgPort(gd->gd_TPort);
  877.    if (gd->gd_LocaleInfo.li_Catalog) CloseCatalog(gd->gd_LocaleInfo.li_Catalog);
  878. #ifndef LINK_LIB
  879.    if (LocaleBase) CloseLibrary(LocaleBase);
  880. #endif
  881.    if (GTLayoutBase) CloseLibrary(GTLayoutBase);
  882.    if (GadToolsBase) CloseLibrary(GadToolsBase);
  883.    if (UtilityBase) CloseLibrary(UtilityBase);
  884.    if (IntuitionBase) CloseLibrary(IntuitionBase);
  885.    if (gd->gd_InputSelected) SelectInput(gd->gd_OldInput);
  886.    if (gd->gd_OutputSelected) SelectOutput(gd->gd_OldOutput);
  887.    if (gd->gd_CTSelected) SetConsoleTask(gd->gd_OldConsoleTask);
  888.    if (gd->gd_Input) Close(gd->gd_Input);
  889.    if (gd->gd_Output) Close(gd->gd_Output);
  890.    if (DOSBase) CloseLibrary(DOSBase);
  891.    if (gd->gd_Public) FreeVec(gd->gd_Public);
  892.    if (gd->gd_PubPool) AsmDeletePool(gd->gd_PubPool, (struct ExecBase*)SysBase);
  893.    if (gd->gd_AnyPool) AsmDeletePool(gd->gd_AnyPool, (struct ExecBase*)SysBase);
  894.    FreeVec(gd);
  895.    return ;
  896. }
  897. /*E*/
  898. /*F*/ PRIVATE VOID dummys2copy(VOID) {}
  899. /*E*/
  900. /*F*/ PRIVATE BOOL opendevs(GD gd)
  901. {
  902.    PD  pd = gd->gd_Public;
  903.    struct GlobalDevData *gdd;
  904.    struct PublicDevData *pdd;
  905.    BOOL rc = FALSE;
  906.    struct TrackType *tt;
  907.    ULONG i;
  908.    static const struct TagItem dummybuffermgnt[] =
  909.    {
  910.       S2_CopyToBuff, (ULONG)&dummys2copy,
  911.       S2_CopyFromBuff, (ULONG)&dummys2copy,
  912.       TAG_DONE
  913.    };
  914.  
  915.    gd->gd_We = FindTask(NULL);
  916.  
  917.    if (gd->gd_TPort = CreateMsgPort())
  918.    {
  919.       pd->pd_TReq.tr_node.io_Message.mn_ReplyPort = gd->gd_TPort;
  920.       if (!OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest*)&pd->pd_TReq, 0L))
  921.       {
  922.          pd->pd_TReq.tr_node.io_Command = TR_ADDREQUEST;
  923.          gd->gd_time.tv_secs = gd->gd_Refresh;
  924.          gd->gd_time.tv_micro = 0;
  925.          gd->gd_TimerOff = 1;
  926.  
  927.          rc = TRUE;
  928.  
  929.          if (gd->gd_S2Port = CreateMsgPort())
  930.          {
  931.             SCANDEVS(gdd, &gd->gd_Devices)
  932.             {
  933.                pdd = gdd->gd_Public;
  934.  
  935.                sprintf(gdd->gd_Title, "%s/%ld", FilePart(gdd->gd_Device), gdd->gd_Unit);
  936.  
  937.                pdd->pd_S2Req.ios2_Req.io_Message.mn_ReplyPort = gd->gd_S2Port;
  938.                if (gdd->gd_Force)
  939.                   pdd->pd_S2Req.ios2_BufferManagement = (VOID*)dummybuffermgnt;
  940.  
  941.                if (!OpenDevice(gdd->gd_Device, gdd->gd_Unit, (struct IORequest*)&pdd->pd_S2Req, 0L))
  942.                {
  943.                   pdd->pd_S2DeviceQuery.SizeAvailable = sizeof(pdd->pd_S2DeviceQuery);
  944.                   pdd->pd_S2Req.ios2_StatData = &pdd->pd_S2DeviceQuery;
  945.                   pdd->pd_S2Req.ios2_Req.io_Command = S2_DEVICEQUERY;
  946.                   d(("S2_DEVICEQUERY\n"));
  947.                   if (DoIO((struct IORequest*)&pdd->pd_S2Req) == 0)
  948.                   {
  949.                      for(i=gdd->gd_NumTT, tt=pdd->pd_TrackedTypes; i; --i, ++tt)
  950.                      {
  951.                         pdd->pd_S2Req.ios2_PacketType = tt->tt_Type;
  952.                         pdd->pd_S2Req.ios2_Req.io_Command = S2_TRACKTYPE;
  953.                         d(("S2_TRACKTYPE %ld\n", tt->tt_Type));
  954.                         if (DoIO((struct IORequest*)&pdd->pd_S2Req) == 0)
  955.                         {
  956.                            tt->tt_Flags |= TTF_TRACKED;
  957.                         }
  958.                         else if ((pdd->pd_S2Req.ios2_Req.io_Error == S2ERR_BAD_STATE) &&
  959.                                  (pdd->pd_S2Req.ios2_WireError == S2WERR_ALREADY_TRACKED))
  960.                         {
  961.                            tt->tt_Flags &= ~TTF_TRACKED;
  962.                         }
  963.                         else
  964.                         {
  965.                            message(gd, REQ_ERROR_TITLE, REQ_ERROR_TRACK, REQ_ERROR_QUITBUTTON,
  966.                                              pdd->pd_S2Req.ios2_PacketType,
  967.                                              pdd->pd_S2Req.ios2_Req.io_Error,
  968.                                              pdd->pd_S2Req.ios2_WireError);
  969.                            rc = FALSE;
  970.                            break;
  971.                         }
  972.                      }
  973.                   }
  974.                   else
  975.                   {
  976.                      message(gd, REQ_ERROR_TITLE, REQ_ERROR_QUERY, REQ_ERROR_QUITBUTTON,
  977.                                              gdd->gd_Device, gdd->gd_Unit);
  978.                      rc = FALSE;
  979.                   }
  980.                }
  981.                else
  982.                {
  983.                   message(gd, REQ_ERROR_TITLE, REQ_ERROR_OPENDEV, REQ_ERROR_QUITBUTTON,
  984.                                              gdd->gd_Device, gdd->gd_Unit);
  985.                   rc = FALSE;
  986.                }
  987.                if (!rc) break;
  988.             }
  989.          }
  990.          else message(gd, REQ_ERROR_TITLE, REQ_ERROR_NOMSGPORT, REQ_ERROR_QUITBUTTON);
  991.       }
  992.       else message(gd, REQ_ERROR_TITLE, REQ_ERROR_OPENDEV, REQ_ERROR_QUITBUTTON,
  993.                               TIMERNAME, UNIT_VBLANK);
  994.    }
  995.    else message(gd, REQ_ERROR_TITLE, REQ_ERROR_NOMSGPORT, REQ_ERROR_QUITBUTTON);
  996.  
  997.    return rc;
  998. }
  999. /*E*/
  1000. /*F*/ PRIVATE GD createenv(ULONG argc, UBYTE **argv)
  1001. {
  1002.    GD gd, new;
  1003.    BOOL ok = FALSE;
  1004.  
  1005.    {
  1006.       LOCALSYSBASE;
  1007.       new = AllocVec(sizeof(struct GlobalData), MEMF_ANY | MEMF_CLEAR);
  1008.       new->gd_SysBase = SysBase;
  1009.    }
  1010.  
  1011.    if (gd = new)
  1012.    {
  1013.       gd->gd_argv = argv;
  1014.       gd->gd_argc = argc;
  1015.       NewList((struct List*)&gd->gd_Devices);
  1016.       if (gd->gd_Public = AllocVec(sizeof(struct PublicData),
  1017.                                                 MEMF_PUBLIC | MEMF_CLEAR))
  1018.       {
  1019.          if (DOSBase = openlib(gd, "dos.library", 37))
  1020.          {
  1021.             if (LocaleBase = openlib(gd, "locale.library", 38))
  1022.                gd->gd_LocaleInfo.li_Catalog = OpenCatalog(NULL, "sana2meter.catalog",
  1023.                                                                OC_Version, CATALOG_VERSION, TAG_DONE);
  1024.  
  1025.             if (UtilityBase = openlib(gd, "utility.library", 37))
  1026.             {
  1027.                if (IntuitionBase = openlib(gd, "intuition.library", 37))
  1028.                {
  1029.                   if (GadToolsBase = openlib(gd, "gadtools.library", 37))
  1030.                   {
  1031. #ifndef LINK_LIB
  1032.                      if (GTLayoutBase = openlib(gd, "gtlayout.library", 24))
  1033.                      {
  1034. #endif
  1035.                         GetProgramName(new->gd_ProgramName, sizeof(new->gd_ProgramName));
  1036.  
  1037.                         if (!(gd->gd_CLI = (Cli() != NULL)))
  1038.                            IconBase = openlib(gd, "icon.library", 0);
  1039.  
  1040.                         if (gd->gd_AnyPool = AsmCreatePool(ANYPOOLKIND, ANYPOOLPUDDLE, ANYPOOLTHRESH,
  1041.                                                       (struct ExecBase*)SysBase))
  1042.                         {
  1043.                            if (gd->gd_PubPool = AsmCreatePool(PUBPOOLKIND, PUBPOOLPUDDLE, PUBPOOLTHRESH,
  1044.                                                          (struct ExecBase*)SysBase))
  1045.                            {
  1046.                               if (parseargs(gd))
  1047.                               {
  1048.                                  if (preparetts(gd))
  1049.                                  {
  1050.                                     openconsole(gd);
  1051.                                     ok = TRUE;
  1052.                                  }
  1053.                               }
  1054.                            }
  1055.                            else message(gd, REQ_ERROR_TITLE, REQ_ERROR_NOPOOL, REQ_ERROR_QUITBUTTON);
  1056.                         }
  1057.                         else message(gd, REQ_ERROR_TITLE, REQ_ERROR_NOPOOL, REQ_ERROR_QUITBUTTON);
  1058. #ifndef LINK_LIB
  1059.                      }
  1060. #endif
  1061.                   }
  1062.                }
  1063.             }
  1064.          }
  1065.          else d(("no dos.library\n"));
  1066.       }
  1067.       else d(("out of memory\n"));
  1068.    }
  1069.    else d(("out of memory\n"));
  1070.  
  1071.    if (!ok && new)
  1072.    {
  1073.       cleanup(new);
  1074.       new = NULL;
  1075.    }
  1076.    return new;
  1077. }
  1078. /*E*/
  1079.  
  1080. /*F*/PUBLIC VOID saveconfig(GD gd)
  1081. {
  1082. #define MAXTOOLTYPE 2048
  1083.    BPTR old, new, cfgfile = 0;
  1084.    struct DiskObject *dob;
  1085.    STRPTR tooltype;
  1086.    STRPTR *oldtt;
  1087.    STRPTR progname;
  1088.    struct GlobalDevData *gdd;
  1089.    BOOL doicon;
  1090.  
  1091.    if (!IconBase)
  1092.       IconBase = openlib(gd, "icon.library", 0);
  1093.  
  1094.    if (IconBase)
  1095.    {
  1096.       if (gd->gd_CLI)
  1097.       {
  1098.          progname = gd->gd_ProgramName;
  1099.          new = Lock("PROGDIR:", ACCESS_READ);
  1100.       }
  1101.       else
  1102.       {
  1103.          struct WBArg *wbarg = ((struct WBStartup *)gd->gd_argv)->sm_ArgList;
  1104.          progname = wbarg->wa_Name;
  1105.          new = DupLock(wbarg->wa_Lock);
  1106.       }
  1107.  
  1108.       if(new)
  1109.       {
  1110.          if (tooltype = allocpvec(gd, MAXTOOLTYPE))
  1111.          {
  1112.             old = CurrentDir(new);
  1113.  
  1114.             doicon = FALSE;
  1115.             if (dob = GetDiskObject(progname))
  1116.             {
  1117.                if (oldtt = DupToolTypes(gd, dob))
  1118.                   doicon = TRUE;
  1119.                else
  1120.                   FreeDiskObject(dob);
  1121.             }
  1122.  
  1123.             SCANDEVS(gdd, &gd->gd_Devices)
  1124.             {
  1125.                if (gdd->gd_FromConfig || !doicon)
  1126.                {
  1127.                   if (!cfgfile) cfgfile = Open(gd->gd_ConfigName, MODE_NEWFILE);
  1128.                   if (cfgfile)
  1129.                   {
  1130.                      sprintf(tooltype, "DEVICE=\"%s\" UNIT=%ld%s%s",
  1131.                                     gdd->gd_Device,
  1132.                                     gdd->gd_Unit,
  1133.                                     gdd->gd_Force ? " FORCE" : "",
  1134.                                     gdd->gd_Active ? "" : " OFF");
  1135.  
  1136.                      strcat(tooltype, " SHOW=\"");
  1137.                      {
  1138.                         struct Watch *w;
  1139.                         BOOL first = TRUE;
  1140.  
  1141.                         SCANWATCHES(w, &gdd->gd_Watches)
  1142.                         {
  1143.                            if ((w->w_Member != MEMBER_TRACKTYPE) && (w->w_Flags & WF_ACTIVE) && w->w_Key)
  1144.                            {
  1145.                               if (first)
  1146.                                  first = FALSE;
  1147.                               else
  1148.                                  strcat(tooltype, ",");
  1149.                               strcat(tooltype, w->w_Key);
  1150.                            }
  1151.                         }
  1152.                      }
  1153.                      strcat(tooltype, "\"");
  1154.                      if (gdd->gd_NumTT)
  1155.                      {
  1156.                         strcat(tooltype, " TRACKTYPE=\"");
  1157.                         {
  1158.                            struct Watch *w;
  1159.                            BOOL first = TRUE;
  1160.  
  1161.                            SCANWATCHES(w, &gdd->gd_Watches)
  1162.                            {
  1163.                               if (w->w_Member == MEMBER_TRACKTYPE)
  1164.                               {
  1165.                                  if (w->w_Key)
  1166.                                  {
  1167.                                     if (first)
  1168.                                        first = FALSE;
  1169.                                     else
  1170.                                        strcat(tooltype, ",");
  1171.  
  1172.                                     sprintf(&tooltype[strlen(tooltype)], "%s%lc",
  1173.                                           w->w_Key, (LONG)TTMASKSEPARATOR[0]);
  1174.                                  }
  1175.                                  sprintf(&tooltype[strlen(tooltype)], "%lc",
  1176.                                     (w->w_Flags & WF_ACTIVE) ? TTMASKACTIVE[0] : TTMASKINACTIVE[0]);
  1177.                               }
  1178.                            }
  1179.                         }
  1180.                         strcat(tooltype, "\"");
  1181.                      }
  1182.                      strcat(tooltype, "\n");
  1183.                      Write(cfgfile, tooltype, strlen(tooltype));
  1184.                   }
  1185.                   else
  1186.                   {
  1187.                      message(gd, REQ_ERROR_TITLE, REQ_ERROR_NOCONFIG,
  1188.                                                    REQ_ERROR_QUITBUTTON, gd->gd_ConfigName);
  1189.                   }
  1190.                }
  1191.                else
  1192.                {
  1193.                   /* DEVICE, UNIT */
  1194.                   sprintf(tooltype, "DEVICE=%s", gdd->gd_Device);
  1195.                   AddToolType(gd, dob, tooltype);
  1196.  
  1197.                   sprintf(tooltype, "UNIT=%ld", gdd->gd_Unit);
  1198.                   AddToolType(gd, dob, tooltype);
  1199.  
  1200.                   sprintf(tooltype, "%sFORCE%s",
  1201.                               gdd->gd_Force ? "(" : "", gdd->gd_Force ? ")" : "");
  1202.                   AddToolType(gd, dob, tooltype);
  1203.  
  1204.                   sprintf(tooltype, "%sOFF%s",
  1205.                               gdd->gd_Active ? "(" : "", gdd->gd_Active ? ")" : "");
  1206.                   AddToolType(gd, dob, tooltype);
  1207.  
  1208.                      /* SHOW watches */
  1209.                   strcpy(tooltype, "SHOW=");
  1210.                   {
  1211.                      struct Watch *w;
  1212.                      BOOL first = TRUE;
  1213.  
  1214.                      SCANWATCHES(w, &gdd->gd_Watches)
  1215.                      {
  1216.                         if ((w->w_Member != MEMBER_TRACKTYPE) && (w->w_Flags & WF_ACTIVE) && w->w_Key)
  1217.                         {
  1218.                            if (first)
  1219.                               first = FALSE;
  1220.                            else
  1221.                               strcat(tooltype, ",");
  1222.                            strcat(tooltype, w->w_Key);
  1223.                         }
  1224.                      }
  1225.                   }
  1226.                   AddToolType(gd, dob, tooltype);
  1227.  
  1228.                   /* TRACKTYPE watches */
  1229.                   strcpy(tooltype, "TRACKTYPE=");
  1230.                   {
  1231.                      struct Watch *w;
  1232.                      BOOL first = TRUE;
  1233.  
  1234.                      SCANWATCHES(w, &gdd->gd_Watches)
  1235.                      {
  1236.                         if (w->w_Member == MEMBER_TRACKTYPE)
  1237.                         {
  1238.                            if (w->w_Key)
  1239.                            {
  1240.                               if (first)
  1241.                                  first = FALSE;
  1242.                               else
  1243.                                  strcat(tooltype, ",");
  1244.  
  1245.                               sprintf(&tooltype[strlen(tooltype)], "%s%lc",
  1246.                                     w->w_Key, (LONG)TTMASKSEPARATOR[0]);
  1247.                            }
  1248.                            sprintf(&tooltype[strlen(tooltype)], "%lc",
  1249.                               (w->w_Flags & WF_ACTIVE) ? TTMASKACTIVE[0] : TTMASKINACTIVE[0]);
  1250.                         }
  1251.                      }
  1252.                      if (first)
  1253.                         strcpy(tooltype, "(TRACKTYPE=)");
  1254.                   }
  1255.                   AddToolType(gd, dob, tooltype);
  1256.  
  1257.                   if (gd->gd_ConfigName)
  1258.                      sprintf(tooltype, "FROM=%s", gd->gd_ConfigName);
  1259.                   else
  1260.                      strcpy(tooltype, "(FROM=)");
  1261.                   AddToolType(gd, dob, tooltype);
  1262.                }
  1263.             }
  1264.  
  1265.             if (doicon)
  1266.             {
  1267.                /* window position */
  1268.                sprintf(tooltype, "LEFT=%ld", gd->gd_Handle->Window->LeftEdge);
  1269.                AddToolType(gd, dob, tooltype);
  1270.                sprintf(tooltype, "TOP=%ld", gd->gd_Handle->Window->TopEdge);
  1271.                AddToolType(gd, dob, tooltype);
  1272.  
  1273.                /* refresh interval */
  1274.                sprintf(tooltype, "REFRESH=%ld", gd->gd_Refresh);
  1275.                AddToolType(gd, dob, tooltype);
  1276.  
  1277.                /* CPS display aging */
  1278.                sprintf(tooltype, "CPSAGING=%ld", gd->gd_CPSAging);
  1279.                AddToolType(gd, dob, tooltype);
  1280.  
  1281.                /* public screen */
  1282.                if (gd->gd_Public->pd_Pubscreen[0])
  1283.                   sprintf(tooltype, "PUBSCREEN=%s", gd->gd_Public->pd_Pubscreen);
  1284.                else
  1285.                   strcpy(tooltype, "(PUBSCREEN=)");
  1286.                AddToolType(gd, dob, tooltype);
  1287.  
  1288.                /* window-in-front enforcing */
  1289.                sprintf(tooltype, "%sSTAYFRONT%s",
  1290.                            gd->gd_StayFront ? "" : "(", gd->gd_StayFront ? "" : ")");
  1291.                AddToolType(gd, dob, tooltype);
  1292.             }
  1293.             else
  1294.             {
  1295.                /* window position */
  1296.                sprintf(tooltype, "LEFT=%ld TOP=%ld REFRESH=%ld CPSAGING=%ld\n",
  1297.                                                      gd->gd_Handle->Window->LeftEdge,
  1298.                                                      gd->gd_Handle->Window->TopEdge,
  1299.                                                      gd->gd_Refresh,
  1300.                                                      gd->gd_CPSAging);
  1301.                Write(cfgfile, tooltype, strlen(tooltype));
  1302.  
  1303.                if (gd->gd_Public->pd_Pubscreen[0])
  1304.                {
  1305.                   sprintf(tooltype, "PUBSCREEN=\"%s\"\n", gd->gd_Public->pd_Pubscreen);
  1306.                   Write(cfgfile, tooltype, strlen(tooltype));
  1307.                }
  1308.  
  1309.                /* window-in-front enforcing */
  1310.                if (gd->gd_StayFront)
  1311.                {
  1312.                   sprintf(tooltype, "STAYFRONT\n");
  1313.                   Write(cfgfile, tooltype, strlen(tooltype));
  1314.                }
  1315.             }
  1316.  
  1317.             if (cfgfile) Close(cfgfile);
  1318.  
  1319.             if (doicon)
  1320.             {
  1321.                PutDiskObject(progname, dob);
  1322.                UnDupToolTypes(gd, dob, oldtt);
  1323.                FreeDiskObject(dob);
  1324.             }
  1325.  
  1326.             UnLock(CurrentDir(old));
  1327.  
  1328.             freepvec(gd, tooltype);
  1329.          }
  1330.       }
  1331.       CloseLibrary(IconBase);
  1332.    }
  1333.  
  1334.    return ;
  1335. }
  1336. /*E*/
  1337.  
  1338. /*F*/ PUBLIC VOID SAVEDS STDARGS main(ULONG argc, UBYTE **argv)
  1339. {
  1340.    int rc = RETURN_FAIL;
  1341.    ULONG m_wait, m_tport, m_s2port, m_recv, m_window;
  1342.    BOOL running;
  1343.    GD gd;
  1344.    PD pd;
  1345.  
  1346.  
  1347.    if (!(gd = createenv(argc, argv))) goto leave;
  1348.    pd = gd->gd_Public;
  1349.  
  1350.    /* initialize gtlayout */
  1351. #ifdef LINK_LIB
  1352.    LT_Init();
  1353. #endif
  1354.  
  1355.    if (gd->gd_List)
  1356.    {
  1357.       const struct NewWatch *nw;
  1358.       Printf("\033[1mTable of keywords (abbrev'd form in parenthesis):\033[0m\n");
  1359.       for (nw = stdwatches; nw->nw_Member != MEMBER_NONE; nw++)
  1360.          Printf("%s (%s)\n", nw->nw_Key, nw->nw_ShortKey);
  1361.       rc = RETURN_OK;
  1362.       goto leave;
  1363.    }
  1364.  
  1365.    if (!opendevs(gd)) goto leave;
  1366.  
  1367.    {
  1368.       struct GlobalDevData *gdd;
  1369.       UWORD fail;
  1370.  
  1371.       SCANDEVS(gdd, &gd->gd_Devices)
  1372.       {
  1373.          updateupdate(gd, gdd);
  1374.          fail = updateglobalstats(gd, gdd);
  1375.          fail += updatespecialstats(gd, gdd);
  1376.          fail += updatetracktype(gd, gdd);
  1377.          if (fail)
  1378.          {
  1379.             updateupdate(gd, gdd);
  1380.             updateglobalstats(gd, gdd);
  1381.             updatespecialstats(gd, gdd);
  1382.             updatetracktype(gd, gdd);
  1383.          }
  1384.       }
  1385.       updateactives(gd);
  1386.    }
  1387.    getspeciallabels(gd);
  1388.  
  1389.    if (!preparemenu(gd)) goto leave;
  1390.  
  1391.    if (!opengui(gd)) goto leave;
  1392.  
  1393.    updategui(gd, TRUE);
  1394.  
  1395.    m_wait = SIGBREAKF_CTRL_C |
  1396.             (m_tport = 1 << gd->gd_TPort->mp_SigBit) |
  1397.             (m_s2port = 1 << gd->gd_S2Port->mp_SigBit) |
  1398.             (m_window = 1 << gd->gd_Handle->Window->UserPort->mp_SigBit);
  1399.  
  1400.    if (gd->gd_NeedTimer)
  1401.    {
  1402.       d(("starting timer\n"));
  1403.       pd->pd_TReq.tr_time = gd->gd_time;
  1404.       SendIO((struct IORequest*)&pd->pd_TReq);
  1405.       gd->gd_TimerOff = 0;
  1406.    }
  1407.  
  1408.    rc = RETURN_OK;
  1409.    for(running = TRUE; running;)
  1410.    {
  1411.       d(("Wait()\n"));
  1412.       m_recv = Wait(m_wait);
  1413.  
  1414.       if (m_recv & SIGBREAKF_CTRL_C)
  1415.       {
  1416.          running = FALSE;
  1417.       }
  1418.  
  1419.       if (m_recv & m_window)
  1420.       {
  1421.          DoWindowCtrl ctrl;
  1422.  
  1423.          running = dowindow(gd, &ctrl);
  1424.          if (running && (ctrl & DOWCTRL_UPDATE))
  1425.          {
  1426.             struct GlobalDevData *gdd;
  1427.             UWORD fail;
  1428.  
  1429.             ctrl &= ~DOWCTRL_REOPEN;
  1430.  
  1431.             if (!gd->gd_TimerOff)
  1432.                AbortIO((struct IORequest*)&pd->pd_TReq);
  1433.  
  1434.             closegui(gd);
  1435.             SCANDEVS(gdd, &gd->gd_Devices)
  1436.             {
  1437.                fail = 0;
  1438.                updateupdate(gd, gdd);
  1439.                if (gdd->gd_GetGlobalStats) fail = updateglobalstats(gd, gdd);
  1440.                if (gdd->gd_GetSpecialStats) fail += updatespecialstats(gd, gdd);
  1441.                if (gdd->gd_GetTrackType) fail += updatetracktype(gd, gdd);
  1442.                if (fail) updateupdate(gd, gdd);
  1443.                /* rh(c)slip seems to leave a DoIO() with the port bit set */
  1444.                SetSignal(0, m_s2port);
  1445.             }
  1446.             updateactives(gd);
  1447.             if (!opengui(gd)) running = FALSE;
  1448.  
  1449.             if (gd->gd_NeedTimer && gd->gd_TimerOff)
  1450.             {
  1451.                d(("starting timer\n"));
  1452.                pd->pd_TReq.tr_time = gd->gd_time;
  1453.                SendIO((struct IORequest*)&pd->pd_TReq);
  1454.                gd->gd_TimerOff = 0;
  1455.             }
  1456.          }
  1457.  
  1458.          if (running && (ctrl & DOWCTRL_REOPEN))
  1459.          {
  1460.             closegui(gd);
  1461.             if (!opengui(gd)) running = FALSE;
  1462.          }
  1463.  
  1464.          if (running && (ctrl & DOWCTRL_SHOWWINDOW))
  1465.          {
  1466.             LT_ShowWindow(gd->gd_Handle, TRUE);
  1467.          }
  1468.       }
  1469.  
  1470.       if (m_recv & m_s2port)
  1471.       {
  1472.          d(("spurious signal from SANA2 MsgPort (mask = %08lx)\n", m_recv));
  1473.       }
  1474.  
  1475.       if (m_recv & m_tport)
  1476.       {
  1477.          struct GlobalDevData *gdd;
  1478.          UWORD fail = 0;
  1479.  
  1480.          if (!gd->gd_TimerOff)
  1481.             WaitIO((struct IORequest*)&pd->pd_TReq);
  1482.  
  1483.          if (gd->gd_NumActives)
  1484.          {
  1485.             SCANDEVS(gdd, &gd->gd_Devices)
  1486.             {
  1487.                if (gdd->gd_GetGlobalStats) fail = updateglobalstats(gd, gdd);
  1488.                if (gdd->gd_GetSpecialStats) fail += updatespecialstats(gd, gdd);
  1489.                if (gdd->gd_GetTrackType) fail += updatetracktype(gd, gdd);
  1490.                /* rh(c)slip seems to leave a DoIO() with the port bit set */
  1491.                SetSignal(0, m_s2port);
  1492.             }
  1493.             if (fail)
  1494.             {
  1495.                closegui(gd);
  1496.                updateupdate(gd, gdd);
  1497.                updateactives(gd);
  1498.                if (!opengui(gd)) running = FALSE;
  1499.             }
  1500.             else
  1501.                updategui(gd, FALSE);
  1502.             if (gd->gd_NeedTimer)
  1503.             {
  1504.                d(("starting timer\n"));
  1505.                pd->pd_TReq.tr_time = gd->gd_time;
  1506.                SendIO((struct IORequest*)&pd->pd_TReq);
  1507.             }
  1508.             else gd->gd_TimerOff = 1;
  1509.          }
  1510.          else gd->gd_TimerOff = 1;
  1511.       }
  1512.    }
  1513.  
  1514.    AbortIO((struct IORequest*)&pd->pd_TReq);
  1515.    WaitIO((struct IORequest*)&pd->pd_TReq);
  1516.  
  1517. leave:
  1518.    if (gd) cleanup(gd);
  1519.  
  1520. #ifdef LINK_LIB
  1521.    LT_Exit();
  1522. #endif
  1523.  
  1524.    exit(rc);
  1525.    return ;
  1526. }
  1527. /*E*/
  1528.  
  1529.